﻿using System;
using System.Windows.Forms;
using System.ServiceProcess;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Remoting.Services;
using System.Diagnostics;


namespace Autorun
{

	static class Program
	{
		private const int LOG_SIZE = 100 * 1024;
		private const int LOG_ROTATION = 3;

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			ServiceBase[] ServicesToRun;

			switch (ApplicationStartInfo.StartMode)
			{
#if DEBUG
				case StartModes.Debug:
					DebugMode();
					break;
#endif
				case StartModes.Service:
					// =================================================================
					// === Start Mode = Windows NT Service =============================
					// =================================================================
					RegisterServer();

					ServicesToRun = new ServiceBase[] { new EngineService() };
					System.ServiceProcess.ServiceBase.Run(ServicesToRun);
					break;
				case StartModes.Server:
					// =================================================================
					// Start Mode = Windows Application Server =========================
					// =================================================================
					RegisterServer();

					Application.EnableVisualStyles();
					Application.SetCompatibleTextRenderingDefault(false);
					Application.Run(new MainServerForm());
					break;
				case StartModes.Client:
					// =================================================================
					// === Start Mode = Windows Application Client =====================
					// =================================================================
					Application.EnableVisualStyles();
					Application.SetCompatibleTextRenderingDefault(false);
					Application.Run(new MainClientForm());
					break;
				default:
					throw new Exception();
			}
		}

#if DEBUG
		static void DebugMode()
		{
			DayRange dr;
			DateTime lastDate;

			lastDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1).AddDays(-1);

			dr = new DayRange(11);
			System.Diagnostics.Debug.WriteLine(dr.ToString());
			// === Try to parse days range ===================================


		}

		public static ServerManagement Connect(bool builtin, string host, int port, string channel, bool register)
		{
			ServiceController controller;
			ServerManagement rc;


			rc = null;
			// === Open the new connection ===================================
			if (builtin == true)
			{
				rc = ServerManagement.Instance;
			}
			else
			{
				// === Try to connect to the Service Controller ==============
				controller = new ServiceController("Autorun.ServerManagement", host);

				try
				{
					ServiceControllerStatus scs;
					scs = controller.Status;
				}
				catch (Exception ex)
				{
					// === Couldn't connect to the Service Controller ========
					controller = null;
#if DEBUG
					MessageBox.Show(ex.ToString());
#endif
				}

				try
				{
					rc = (ServerManagement)Activator.GetObject(
							 typeof(ServerManagement),
							 String.Format("{0}://{1}:{2}/{3}", channel, host, port, "ServerManagement"),
							 typeof(ServerManagement));
					string connectedDomain;
					connectedDomain = rc.Information.Domain;
					//TODO: Le AddHandler ne fonctionne pas pour des raisons de security policies
					//AddHandler My.Proxy.Engine.OnStatus, AddressOf myEngine_OnStatus

				}
				catch (Exception ex)
				{
#if DEBUG
					MessageBox.Show(ex.ToString());
#else
					MessageBox.Show("The server did not answer in a timely fashion.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
#endif
				}
			}

			return rc;
		}

#endif

		private static void RegisterServer()
		{
			string channel;
			int port;
			ITrackingHandler handler;
			string logFile;

			channel = ServerManagement.Instance.Configuration.RemoteChannel.Trim().ToLower();
			port = ServerManagement.Instance.Configuration.RemotePort;


			if (Properties.Settings.Default.TrackingServices == true)
			{
				// === Before adding the tracking listener, redirect traces to a log file
				logFile = Path.Combine(
					ApplicationStartInfo.RootDirectory,
					string.Format("{0}.log", Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0])));
				FileStreamWithBackup fs = new FileStreamWithBackup(logFile, LOG_SIZE, LOG_ROTATION, FileMode.Append);
				fs.CanSplitData = false;
				TextWriterTraceListenerWithTime listener = new TextWriterTraceListenerWithTime(fs);
				Trace.AutoFlush = true;
				Trace.Listeners.Add(listener);

				handler = new TrackingHandler();
				TrackingServices.RegisterTrackingHandler(handler);
			}

			switch (channel)
			{
				case "tcp":
					ChannelServices.RegisterChannel(new TcpChannel(port), false);
					RemotingConfiguration.RegisterWellKnownServiceType(typeof(ServerManagement), "ServerManagement", WellKnownObjectMode.Singleton);
					break;
				default:
					throw new InvalidOperationException(string.Format("The channel type '{0}' is unknonw or unsupported", channel));
			}
		}
	}


}
